package com.nineclock.system.service.impl;

import com.alibaba.fastjson.JSON;
import com.aliyun.oss.OSSClient;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nineclock.common.constant.NcConstant;
import com.nineclock.common.constant.SMSConstant;
import com.nineclock.common.entity.Result;
import com.nineclock.common.entity.UserInfo;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.oss.OssProperties;
import com.nineclock.common.redis.CacheService;
import com.nineclock.common.utils.CurrentUserHolder;
import com.nineclock.common.utils.DateTimeUtil;
import com.nineclock.common.utils.UUIDUtils;
import com.nineclock.system.dto.SysCompanyUserAdminDto;
import com.nineclock.system.mapper.SysCompanyMapper;
import com.nineclock.system.mapper.SysCompanyUserMapper;
import com.nineclock.system.pojo.*;
import com.nineclock.system.service.SysCompanyService;
import com.nineclock.system.service.SysCompanyUserRoleService;
import com.nineclock.system.service.SysRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Map;

@Service
public class SysCompanyServiceImpl extends ServiceImpl<SysCompanyMapper, SysCompany> implements SysCompanyService {

    @Lazy
    @Autowired
    private OSSClient ossClient;

    @Autowired
    private OssProperties ossProperties;

    @Autowired
    private SysCompanyUserMapper sysCompanyUserMapper;

    @Autowired
    private CacheService cacheService;

    @Autowired
    private SysCompanyUserRoleService sysCompanyUserRoleService;

    @Autowired
    private SysRoleService sysRoleService;


    /**
     * 查询当前企业信息
     *
     * @return
     */
    @Override
    public Result selectCurrentCompany() {

        UserInfo userInfo = CurrentUserHolder.get();

        if (userInfo == null) {
            return Result.error();
        }

        Long companyId = userInfo.getCompanyId();
        if (companyId == null || companyId == 0) {
            return Result.error();
        }

        SysCompany result = this.getById(companyId);

        return Result.success(result);
    }

    /**
     * 上传企业图片
     *
     * @param multipartFile
     * @return
     */
    @Override
    public Result uploadOss(MultipartFile multipartFile) {

        UserInfo userInfo = CurrentUserHolder.get();
        if (userInfo == null) {
            return Result.errorMessage(ResponseEnum.UNAUTHORIZED.getMessage());
        }

        Long companyId = userInfo.getCompanyId();
        if (companyId == null || companyId == 0) {
            return Result.errorMessage(ResponseEnum.COMPANY_NOT_FOUND.getMessage());
        }

        if (multipartFile == null || multipartFile.isEmpty() || multipartFile.getSize() == 0) {
            return Result.errorMessage("文件参数非法");
        }

        if (!NcConstant.ALLOWED_IMG_TYPES.contains(multipartFile.getContentType())) {
            return Result.errorMessage("请上传正确图片");
        }

        if (multipartFile.getSize() > NcConstant.maxFileSize) {
            return Result.errorMessage(ResponseEnum.FILE_SIZE_EXCEED_MAX_LIMIT.getMessage());
        }

        String originalFilename = multipartFile.getOriginalFilename();

        if (StringUtils.isBlank(originalFilename)) {
            return Result.errorMessage("上传失败");
        }

        String filePrefixName = UUIDUtils.getUUID();//创建的文件名

        String postFixFileName = originalFilename.substring(originalFilename.lastIndexOf("."));//截取文件的后缀名

        SysCompany company = this.getById(companyId);
        if (company == null) {
            return Result.errorMessage(ResponseEnum.COMPANY_NOT_FOUND.getMessage());
        }

        String key = company.getName() + "/" + DateTimeUtil.dateToStr(new Date(), DateTimeUtil.TIME_FORMAT_2) + "/" + filePrefixName + postFixFileName;

        try {
            InputStream inputStream = multipartFile.getInputStream();
            ossClient.putObject(ossProperties.getBucketName(), key, inputStream);

            String host = ossProperties.getHost();
            String url = host.concat(key);

            return Result.success(url);

        } catch (IOException e) {
            return Result.error();
        }


    }

    /**
     * 保存企业logo修改
     *
     * @param json
     * @return
     */
    @Override
    public Result updateCompany(String json) {

        UserInfo userInfo = CurrentUserHolder.get();
        if (userInfo == null) {
            return Result.errorMessage(ResponseEnum.UNAUTHORIZED.getMessage());
        }

        Long userInfoId = userInfo.getId();

        Map map = JSON.parseObject(json, Map.class);

        String name = (String) map.get("name");
        String logo = (String) map.get("logo");

        if (StringUtils.isBlank(name) || StringUtils.isBlank(logo)) {
            return Result.errorMessage(ResponseEnum.INVALID_PARAM_ERROR.getMessage());
        }

        Long companyId = userInfo.getCompanyId();
        if (companyId == null || companyId == 0) {
            return Result.errorMessage(ResponseEnum.COMPANY_NOT_FOUND.getMessage());
        }

        SysCompany company = this.getById(companyId);

        if (company == null) {
            return Result.errorMessage(ResponseEnum.COMPANY_NOT_FOUND.getMessage());
        }

        if (!company.getUserId().equals(userInfoId) || !company.getMainManagerId().equals(userInfoId)) {
            return Result.errorMessage(ResponseEnum.FILE_WRITE_NOT_PERMIT.getMessage());
        }

        company.setLogo(logo);
        company.setName(name);

        this.updateById(company);


        return Result.success(ResponseEnum.SUCCESS);
    }

    /**
     * 获取当前登录企业管理员
     *
     * @return
     */
    @Override
    public Result getCurrentAdmin() {

        UserInfo userInfo = CurrentUserHolder.get();

        if (userInfo == null) {
            return Result.errorMessage(ResponseEnum.UNAUTHORIZED.getMessage());
        }

        if (userInfo.getCompanyId() == null || userInfo.getCompanyId() == 0) {
            return Result.errorMessage("您当前登录账号未设置企业");
        }

        SysCompanyUser currentCompanyAdmin = sysCompanyUserMapper.getCurrentPositionUser(userInfo.getCompanyId(), NcConstant.ADMIN_ROLE_SYS);

        if (currentCompanyAdmin == null) {
            return Result.errorMessage(ResponseEnum.COMPANY_ADMIN_NOT_EXISTS.getMessage());
        }

        return Result.success(currentCompanyAdmin);
    }

    /**
     * 修改企业管理员
     *
     * @param dto
     */
    @Override
    @Transactional
    public void updateAdmin(SysCompanyUserAdminDto dto) {

        if (dto == null || StringUtils.isBlank(dto.getCode()) || dto.getUserId() == null || dto.getUserId() == 0) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        String code = dto.getCode();
        Integer userId = dto.getUserId();

        UserInfo userInfo = CurrentUserHolder.get();

        if (userInfo == null) {
            throw new NcException(ResponseEnum.UNAUTHORIZED);
        }

        if (userInfo.getCompanyId() == null || userInfo.getCompanyId() == 0) {
            throw new NcException(ResponseEnum.COMPANY_NOT_FOUND);
        }

        String username = userInfo.getUsername();
        if (StringUtils.isBlank(username)) {
            throw new NcException(ResponseEnum.COMPANY_ADMIN_NOT_EXISTS);
        }

        SysCompanyUser sysCompanyUser = sysCompanyUserMapper.selectById(userId);
        if (sysCompanyUser == null) {
            throw new NcException(ResponseEnum.COMPANY_ADMIN_NOT_EXISTS);
        }

        String mobile = sysCompanyUser.getMobile();
        if (StringUtils.isBlank(mobile)) {
            throw new NcException(ResponseEnum.INVALID_PHONE_NUMBER);
        }

        String key = SMSConstant.SMS_CHANGE_MANAGER_KEY_PREFIX.concat(mobile);

        String redisCode = cacheService.get(key);

        if (StringUtils.isBlank(redisCode)) {
            throw new NcException(ResponseEnum.INVALID_VERIFY_CODE);
        }

        if (!code.equals(redisCode)) {
            throw new NcException(ResponseEnum.INVALID_VERIFY_CODE);
        }
        
        cacheService.delete(key);

        SysRole role = sysRoleService.getOne(Wrappers.<SysRole>lambdaQuery()
                .eq(SysRole::getRoleName, NcConstant.ADMIN_ROLE_SYS)
                .eq(SysRole::getCompanyId, userInfo.getCompanyId()));
        if (role == null) {
            throw new NcException(ResponseEnum.UPDATE_OPERATION_FAIL);
        }

        SysCompanyUserRole userRoleServiceOne = sysCompanyUserRoleService.getOne(Wrappers.<SysCompanyUserRole>lambdaQuery()
                .eq(SysCompanyUserRole::getCompanyId, userInfo.getCompanyId())
                .eq(SysCompanyUserRole::getRoleId, role.getId()));

        SysCompanyUser currentUser = sysCompanyUserMapper.selectOne(Wrappers.<SysCompanyUser>lambdaQuery()
                .eq(SysCompanyUser::getUserName, username)
                .eq(SysCompanyUser::getCompanyId, userInfo.getCompanyId()));

        if (currentUser == null) {
            throw new NcException(ResponseEnum.COMPANY_ADMIN_NOT_EXISTS);
        }

        if (userRoleServiceOne != null && currentUser.getUserId().equals(userInfo.getId())) {
            boolean flag = sysCompanyUserRoleService.update(Wrappers.<SysCompanyUserRole>lambdaUpdate()
                    .eq(SysCompanyUserRole::getCompanyId, userInfo.getCompanyId())
                    .eq(SysCompanyUserRole::getRoleId, role.getId())
                    .set(SysCompanyUserRole::getCompanyUserId, userId));
            if (!flag) {
                throw new NcException(ResponseEnum.UPDATE_OPERATION_FAIL);
            }
        } else {
            throw new NcException(ResponseEnum.USER_NOT_COMPANY_ADMIN);
        }

        boolean flag = this.update(Wrappers.<SysCompany>lambdaUpdate().eq(SysCompany::getMainManagerId, userInfo.getCompanyId())
                .set(SysCompany::getMainManagerId, userId));

        if (!flag) {
            throw new NcException(ResponseEnum.UPDATE_OPERATION_FAIL);
        }

    }


}
